home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 42 / Amiga Format AFCD42 (Issue 126, Aug 1999).iso / -serious- / programming / basic / udpchat / old_stuff / udp_chatv1.9.asc < prev    next >
Encoding:
Text File  |  1999-05-14  |  23.1 KB  |  661 lines

  1. ;
  2. ;                      UDP Chat code V1.9   21/4/98
  3. ;
  4. ;    This code sends and receives UDP data packets like a
  5. ;  a simple IRC client, and  checks wether they have arrived
  6. ;  at their destination, and allows other copies of this
  7. ;  program to log in to this one (can act as a server or client).
  8. ;
  9. ;  Written by Anton Reinauer <anton@ww.co.nz>.
  10. ;  GUI: Alvaro Thompson <alvaro@enterprise.net> - And awful hacks
  11. ;  by me to his nice font sensitive code :-)
  12. ;        - typical bloody games programmer ;-)
  13. ;
  14. ;  Thanks to Paul Burkey for TCP_Funcs and to Dr. Ercole Spiteri
  15. ;  for TCP-to-Blitz.
  16. ;
  17. ;  Turn overflow errors off in Debugger options,
  18. ;  and have amigalibs.res resident in compiler options.
  19.  
  20.  
  21. WBStartup
  22. NoCli
  23. Hostname.s="localhost"  ; default destination host address
  24. #PORT=3001              ; default destination port to send data to
  25. #LOCALPORT=3001
  26. #NO_CONNECTION=1        ; are we connected, or have we been connected to the Internet since bootup?
  27.                         ; 1 for not been connected, 0 for have/are connected.
  28.                         ; This is only needed for a bug in older versions of Miami
  29.                         ; when running UDP_Chat locally- V2.1 of Miami works Ok.
  30. #MAX_NUMBER_PLAYERS=8
  31. GAME_NAME.s="UDP_Test"
  32.  
  33. INCLUDE "Net_Protocol_Header.bb2"  ; Net protocol constants
  34. INCLUDE "UDPHeader.bb2"  ;Standard TCP/UDP library structures
  35.  
  36. DEFTYPE .w
  37.  
  38. packet_number.l=0
  39. online=0
  40. my_number=0
  41. last_message_number.l=0
  42. free_message.l=0
  43. ;********************************************************
  44.  
  45. NEWTYPE .message_status
  46.   number.l     ; packet number
  47.   ack.w        ; has it been received yet?
  48.   timestamp.l  ; when was it sent?
  49.   message.s    ; message
  50.   resends.w    ; how many times has it been re-sent?
  51.   player       ; which player was it sent too?
  52. End NEWTYPE
  53.  
  54. NEWTYPE .player_info
  55. status.w
  56. ascii_host_string.s
  57. player_colour.w
  58. score.l
  59. name.s
  60. nick.s
  61. End NEWTYPE
  62.  
  63. ;*******************************************************
  64. .Dims
  65.  
  66. Dim messages.message_status(100)
  67. Dim host.sockaddrin(8), hostlen.l(8)
  68. Dim players.player_info(8)
  69.  
  70. DEFTYPE .sockaddrin temphost
  71.  
  72. INCLUDE "UDPFuncs.bb2"  ; basic UDP socket functions
  73.  
  74. ;*******************************************************
  75.  
  76. .Print_String                ; Print a string in window and scroll if necessary
  77. Statement Print_String{text$}
  78.   SHARED ypos
  79.   If ypos<200
  80.     ypos+10
  81.   Else
  82.     WScroll 10,60,590,220,0,10
  83.   EndIf
  84.  
  85.   WLocate 10,ypos
  86.   Print text$               ; print string received
  87. End Function
  88.  
  89. .Get_Packet_Source            ; Check if packet has come from player already logged on.
  90. Function.w Get_Packet_Source{}
  91.  SHARED host(),temphost
  92.  i=0
  93.  Repeat                    ; check for each player (hostname and socket)
  94.    i+1
  95.    If host(i)\sin_addr\s_addr=temphost\sin_addr\s_addr AND  host(i)\sin_port=temphost\sin_port
  96.      exit=1
  97.    EndIf
  98.    If i=8 AND exit=0       ; if at end of players and no match is found
  99.      i=-1
  100.      exit=1
  101.    EndIf
  102.  Until  exit=1
  103.  
  104.  Function Return i
  105. End Function
  106.  
  107. .Get_Ascii_Address                     ; build a.b.c.d numerical address from long number
  108. Function.s Get_Ascii_Address{address.l}
  109.   string_address.l=Inet_NtoA_(address) ; get memory address of ASCII string version of host address (a.b.c.d)
  110.   If string_address=0
  111.     Function Return ""
  112.   EndIf
  113.   Repeat                               ; build ASCII host string
  114.     letter.b=(Peek.b(string_address))
  115.     If letter<>0
  116.       temp$=temp$+Chr$(letter)
  117.     EndIf
  118.     string_address+1
  119.   Until letter=0
  120.   Function Return temp$
  121. End Function
  122.  
  123. .Send_Reliable_Message         ; this message is checked to see if it has arrived, and resent if not
  124. Statement Send_Reliable_Message{send_string.s,player}       ; if no confirmation can be made, link is considered lost
  125.  SHARED messages(),free_message,last_message_number,packet_number
  126.  
  127.   messages(free_message)\number=packet_number,False,Ticks,send_string.s,0,player  ; log message in message array
  128.   If messages(last_message_number)\ack=True
  129.     last_message_number=free_message
  130.   EndIf
  131.  
  132.   WriteUDP{&send_string.s,Len(send_string.s),player}   ; send message
  133.   packet_number+1               ; set packet number to next free packet number (+1)
  134.   free_message+1
  135.   If free_message=101 Then free_message=0    ; if packet number >100 then wrap back to 0
  136.  
  137. End Statement
  138.  
  139.  
  140.  
  141. .Get_Host_By_Name        ; get a host structure by name (if exists), from a name server
  142. Function Get_Host_By_Name{host$,port.w,player}
  143.   SHARED host(),hostlen()
  144.  
  145.   *a.hostent=gethostbyname_(host$)     ; set up destination address to send packets to
  146.   If *a.hostent=0
  147.     WLocate 10,18
  148.     Print "    No connection to host           "
  149.     Function Return False
  150.   Else
  151.     WLocate 10,18
  152.     Print "Type in data, and hit return to send"
  153.   EndIf
  154.  
  155.   ;Copy Details to our Sockaddrin structure
  156.  
  157.   bb=CopyMem_(*a.hostent\h_addr_list\ItemA,&host(player)\sin_addr,*a.hostent\h_length)
  158.  
  159.   host(player)\sin_port=port       ;Set port number
  160.   host(player)\sin_family=2        ;Set type to AT_INET
  161.   hostlen(player)=SizeOf.sockaddrin        ;Get length of structure sockaddrin
  162.  
  163.   Function Return True
  164. End Function
  165.  
  166. .Get_Host_By_Address      ; get a host structure by address (if exists), from a name server
  167. Function.b Get_Host_By_Address{address.l,port,player}
  168.   SHARED host(),hostlen()
  169.  
  170.   *a.hostent=gethostbyaddr_(address,4,2)  ; check wether host exists- we're not being shammed
  171.  
  172.   If *a.hostent=0
  173.     Function Return False
  174.   EndIf
  175.  
  176.   bb=CopyMem_(*a.hostent\h_addr_list\ItemA,&host(player)\sin_addr,*a.hostent\h_length) ; copy details to player's host
  177.                                                                                        ; newtype to host
  178.   host(player)\sin_port=port               ;Set port number
  179.   host(player)\sin_family=2                ;Set type to AT_INET
  180.   hostlen(player)=SizeOf.sockaddrin        ;Get length of structure sockaddrin
  181.   Function Return True
  182. End Function
  183.  
  184. .Localhost_Name       ; get our internet address- it changes each time we log in to our ISP
  185. Function.s Localhost_Name{}
  186.     If OpenFile (0,"ENV:HOSTNAME")
  187.        FileInput 0
  188.        While NOT Eof(0)
  189.          a$=a$+Inkey$
  190.        Wend
  191.        CloseFile 0
  192.        WindowInput 0
  193.        Function Return a$
  194.     EndIf
  195.     Function Return "localhost"
  196. End Function
  197.  
  198. .Resend_Message       ; resend a message
  199. Function Resend_Message{message_number}
  200.   SHARED messages()
  201.   messages(message_number)\timestamp=Ticks
  202.   messages(message_number)\resends+1
  203.   If messages(message_number)\resends>5  ; is host not responding? After 5 retries consider link broken.
  204.      Print_String{"Host not responding to Packet no: " + Str$(message_number)}
  205.      Function Return False
  206.   Else
  207.      WriteUDP{&messages(message_number)\message,Len(messages(message_number)\message),messages(message_number)\player}
  208.      Print_String{"Resent Packet no:" + Str$(message_number)}
  209.      Function Return True
  210.   EndIf
  211. End Statement
  212.  
  213. .Find_Next_Message
  214. Statement Find_Next_Message{}
  215. SHARED last_message_number,messages(),free_message
  216.  
  217.   exit=0
  218.   Repeat              ; find next unacknowledged message in array
  219.  
  220.     last_message_number+1
  221.     If last_message_number=101 Then last_message_number=0
  222.  
  223.     If last_message_number=free_message  ; if have got to free_message then there are no messages waiting to be acknowledged
  224.       If last_message_number=0
  225.         last_message_number=100
  226.         exit=1
  227.       Else
  228.         last_message_number-1
  229.         exit=1
  230.       EndIf
  231.     Else
  232.       If messages(last_message_number)\ack=False   ; we've found the next unacknowledged message in the array
  233.         exit=1
  234.       EndIf
  235.     EndIf
  236.  
  237.   Until exit=1
  238. End Statement
  239.  
  240. .Acknowledge_Packet   ; mark message as been sucessfully sent
  241. Statement Acknowledge_Packet{ack_packet_number}
  242.   SHARED last_message_number,free_message,messages()
  243.  
  244.   a=last_message_number
  245.   exit=0
  246.   Repeat
  247.     If messages(a)\number=ack_packet_number   ; find message in sent messages array
  248.       messages(a)\ack=True         ; note it as being received
  249.       Format "0000"
  250.       current_time.l=Ticks
  251.       current_lag=current_time-messages(a)\timestamp ; calculate lag
  252.       b$=Str$(current_lag)
  253.       WLocate 142,32
  254.       Print b$         ; print lag onscreen
  255.       Format""
  256.       exit=1
  257.     EndIf
  258.     a+1
  259.     If a=101 Then a=0    ; if at end of array, jump to beginning
  260.   Until exit=1
  261.  
  262.   If a=last_message_number+1 OR (a=0 AND last_message_number=100)   ; if last message unacknowledged is acknowledged
  263.     Find_Next_Message{}                                             ; then find next unacknowledged message
  264.   Else                ; we have lost a packet- resend last packet number!
  265.     If messages(last_message_number)\timestamp-current_time > current_lag+5    ; if its behind the current lag resend it
  266.       Print_String{"Received packet ACK out of order, resending last unacknowledged packet."}
  267.       If Resend_Message{last_message_number}= False   ; if run out of resends- time out message
  268.         messages(last_message_number)\timestamp=current_time+500  ; stop it resending the packet infinitely
  269.         Acknowledge_Packet{last_message_number}       ; wipe message off message acknowledge array
  270.       EndIf
  271.     EndIf
  272.   EndIf
  273. End Statement
  274.  
  275. .Requested_Connection      ; a player is trying to log in to us
  276. Function.s Requested_Connection{incoming_string.s}
  277.   SHARED sock,players(),host(),hostlen(),GAME_NAME,CP_REP_ACCEPT.s,CP_REP_REJECT.s
  278.   SHARED send$,player,temphost,temphostlen,CP_REP_PLAYER_INFO.s
  279.   SHARED packet_number,online,my_number
  280.  
  281.   If online<2
  282.     dummy=3
  283.     Repeat            ; build game name string from incoming request
  284.       b$=Mid$(incoming_string,dummy,1)
  285.       If b$<>Chr$(0)
  286.         c$=c$+b$
  287.       EndIf
  288.       dummy+1
  289.     Until b$=Chr$(0) OR dummy=(Len(incoming_string))
  290.  
  291.     If b$=Chr$(0)
  292.       If c$=GAME_NAME.s            ; if request is for correct game
  293.         protocol=Asc(Right$(incoming_string,1))
  294.         If protocol=#NET_PROTOCOL_VERSION  ; check wether using the same protocol
  295.           a$="Connection request from "
  296.           player=1
  297.           exit=0
  298.           Repeat      ;check if a spare player slot is availiable
  299.             player+1
  300.             If players(player)\status=0
  301.               exit=1
  302.             Else
  303.               If player=#MAX_NUMBER_PLAYERS-1
  304.                 exit=1
  305.                 player=-1
  306.               EndIf
  307.             EndIf
  308.           Until exit=1
  309.  
  310.           If player>0     ; connection accepted
  311.             If Get_Host_By_Address{&temphost\sin_addr\s_addr,temphost\sin_port,player}=False
  312.               Function Return Str$(temphost\sin_addr\s_addr) + "- Host not found!"
  313.             EndIf
  314.  
  315.             players(player)\status=1
  316.             my_number=1
  317.             players(1)\status=1       ; We are now online as Server
  318.             If Get_Host_By_Address{&host(0)\sin_addr\s_addr,host(0)\sin_port,1}= False  ; put our details in Server Slot
  319.               Function Return Str$(host(0)\sin_addr\s_addr) + "- Host not found!"
  320.             EndIf
  321.  
  322.             temp$=Get_Ascii_Address{host(player)\sin_addr\s_addr}
  323.  
  324.             a$=a$+temp$ + "  Port: " + Str$(host(player)\sin_port)
  325.             players(player)\ascii_host_string=temp$   ; store it
  326.  
  327.             For i=1 To #MAX_NUMBER_PLAYERS
  328.               If i<> player AND players(i)\status=1
  329.                 If i>1
  330.                   ; build player info string
  331.                   send$=CP_REP_PLAYER_INFO.s + Mkl$(packet_number) + Mki$(player) + Mkl$(host(player)\sin_addr\s_addr)
  332.                   send$=send$ + Mki$(host(player)\sin_port) + Chr$(players(player)\player_colour)
  333.                   send$=send$ + Mkl$(players(player)\score)
  334.                   send$=send$ + players(player)\name + Chr$(0) + players(player)\nick
  335.  
  336.                   Send_Reliable_Message{send$,i}    ; tell others players that new player is online
  337.                                                     ; and give them new players info.
  338.                 EndIf
  339.  
  340.                 send$=CP_REP_PLAYER_INFO.s + Mkl$(packet_number) + Mki$(i) + Mkl$(host(i)\sin_addr\s_addr)
  341.                 send$=send$ + Mki$(host(i)\sin_port) + Chr$(players(i)\player_colour)
  342.                 send$=send$ + Mkl$(players(i)\score)
  343.                 send$=send$ + players(i)\name + Chr$(0) + players(i)\nick
  344.  
  345.                 Send_Reliable_Message{send$,player}    ; tell new player of others online
  346.                                                        ; and give them their info.
  347.               EndIf
  348.  
  349.             Next
  350.  
  351.  
  352.             send$=CP_REP_ACCEPT.s + Mkl$(packet_number)
  353.             send$=send$ + Mki$(host(0)\sin_port)+ Chr$(player) + Mki$(map)  ; send connection accepted back to client
  354.             online=1
  355.             Function Return a$
  356.           Else
  357.             a$=a$+"- no spare player slot!"
  358.           EndIf
  359.         Else
  360.           a$="Connection request- Incorrect Protocol: "+Str$(protocol)
  361.         EndIf
  362.       Else
  363.         a$="Wrong game name connection request: "+b$
  364.       EndIf
  365.     Else
  366.       a$="Connection request- Unknown error!"
  367.     EndIf
  368.   Else
  369.     a$="Connection Request rejected- host already logged on as Client"
  370.   EndIf
  371.  
  372.   send$=CP_REP_REJECT.s +  Mkl$(packet_number) + a$  ; send connection rejected back with reason
  373.   player=0                    ; send packet back to temphost
  374.   Function Return a$
  375. End Function
  376.  
  377. .Decode_Packet      ; Decode incoming packet and act accordingly
  378. Statement Decode_Packet{incoming_string.s}
  379.   SHARED players(),host(),GAME_NAME.s,temphost,temphostlen,online,REL_PACKET_ACK.s,CP_REP_ACCEPT.s
  380.   SHARED send$,player,my_number
  381.   packet_type=Asc(Left$(incoming_string,1))
  382.   packet_not_connected=0   ; check to see if packet should be from reliable online source
  383.   player=Get_Packet_Source{}  ; check to see if packet is from reliable online source
  384.   return_message=0
  385.  
  386.   Select packet_type         ; as set in `Net_Protocol_Header.bb2'
  387.     Case  #CONTROL_PACKET    ; connection or control information
  388.       packet_type=Asc(Mid$(incoming_string,2))
  389.       Select packet_type
  390.         Case #CP_REQ_CONNECT      ; request to login to Server
  391.           a$=Requested_Connection{incoming_string}
  392.           packet_not_connected=1
  393.           return_message=2
  394.         Case #CP_REP_ACCEPT       ; We Received confirmation of logon from Server
  395.           online=2
  396.           packet_number.l=Cvl(Mid$(incoming_string,3,4))
  397.           my_number=Val(Mid$(incoming_string,9,1))
  398.           map.w=Cvi(Mid$(incoming_string,10,2))
  399.           players(1)\status=1
  400.           a$="Connection Accepted"
  401.           return_message=3
  402.         Case #CP_REP_REJECT       ; Our logon request was rejected by host
  403.           packet_number.l=Cvl(Mid$(incoming_string,3,4))
  404.           a$=Mid$(incoming_string,7)
  405.           return_message=3
  406.         Case #CP_REP_PLAYER_INFO  ; Information about new player that has just logged on
  407.           newplayer=Cvi(Mid$(incoming_string,7,2))
  408.           packet_number.l=Cvl(Mid$(incoming_string,3,4))
  409.           address.l=Cvl(Mid$(incoming_string,9,4))
  410.           If Get_Host_By_Address{&address,Cvi(Mid$(incoming_string,13,2)),newplayer}=True
  411.             ascii_address.s=Get_Ascii_Address{address}
  412.             players(newplayer)\status=1,ascii_address.s
  413.             players(newplayer)\player_colour=Val(Mid$(incoming_string,15,1))
  414.             players(newplayer)\score=Cvi(Mid$(incoming_string,16,4))
  415.             a$="New player at- " + ascii_address.s + " Port: " + Str$(host(newplayer)\sin_port)
  416.           Else
  417.             a$="New player at unknown host!"
  418.           EndIf
  419.           return_message=3
  420.        End Select
  421.  
  422.     Case #REL_STRING_END     ; basic string message received from a player
  423.       packet_number.l=Cvl(Mid$(incoming_string,2,4))
  424.       a$=Str$(packet_number) + "," + Str$(player)  + ": " + Mid$(incoming_string,6,Len(incoming_string)-6)
  425.       return_message=3
  426.  
  427.     Case #REL_PACKET_ACK     ; a message has been received by a player
  428.       packet_number.l=Cvl(Mid$(incoming_string,2,4))
  429.       a$=": Packet no. " + Str$(packet_number) + " arrived at destination."
  430.       Acknowledge_Packet{packet_number}
  431.  
  432.     Default                        ; unknown packet type received
  433.       If player<0                  ; if from unknown source
  434.         temp$=Get_Ascii_Address{temphost\sin_addr\s_addr} + "Port: " + Str$(temphost\sin_port)
  435.       Else                         ; from known source
  436.         temp$="Player: " + Str$(player)
  437.       EndIf
  438.       a$="Unknown Packet from: " + temp$
  439.   End Select
  440.  
  441.   If player<0 AND packet_not_connected=0
  442.     Print_String{"Warning: Packet from unknown source!"}
  443.     Statement Return
  444.   EndIf
  445.  
  446.   If return_message>0
  447.     If return_message=2
  448.       Send_Reliable_Message{send$,player}  ; send packet back (return_message=2)
  449.     Else
  450.       If return_message=3  ; send packet acknowledgment back
  451.         send$=REL_PACKET_ACK.s + Mkl$(packet_number)
  452.       EndIf
  453.       WriteUDP{&send$,Len(send$),player}  ; return a message back if return_message = 1 or 3
  454.     EndIf
  455.   EndIf
  456.  
  457.   a$="R "+a$
  458.   Print_String{a$}   ; print message in the window
  459. End Statement
  460.  
  461. ;****************************************
  462.  
  463.  
  464. Gosub Init_Gui
  465.  
  466. ypos=40
  467. xpos=10
  468. messages(free_message)\ack=True
  469.  
  470. CNIF #NO_CONNECTION=1    ; if not connected to the `net- just running locally
  471.  
  472.   If ConnectUDP {Hostname,#LOCALPORT}              ; bind socket to local port
  473.      Print_String {"Bound to "+Hostname+" "+ Str$(port_used)}
  474.      WLocate 510,4
  475.      Print "Bound to: ",port_used
  476.   Else
  477.      Print_String { "Error in setting up UDP at Port "+ Str$(port_used)}
  478.      Goto Exit
  479.   EndIf
  480.  
  481.   If Get_Host_By_Name {Hostname,#PORT,0}  :EndIf   ; Set up our host details
  482.  
  483. CELSE                   ; are connected to the net or have been since computer was booted up
  484.   If ConnectUDP {Localhost_Name{},#LOCALPORT}              ; bind socket to local port
  485.      Print_String {"Bound to "+Hostname+" "+ Str$(port_used)}
  486.      WLocate 510,4
  487.      Print "Bound to: ",port_used
  488.   Else
  489.      Print_String { "Error in setting up UDP at Port "+ Str$(port_used)}
  490.      Goto Exit
  491.   EndIf
  492.  
  493.   If Get_Host_By_Name {Localhost_Name{},#PORT,0}   :EndIf     ; Set up our host details
  494. CEND
  495.  
  496. ResetTimer
  497.  
  498. ;****************************************
  499.  
  500. .Main
  501.  
  502. Repeat
  503.  
  504.     VWait   ; pause a bit to allow prog to multitask nicely.
  505.  
  506.     If ev.l=$40
  507.       Select GadgetHit
  508.         Case51           ; Try to connect to a Server
  509.           If online=0
  510.             If Get_Host_By_Name{GTGetString(0,51), GTGetInteger(0,52),1}=True
  511.               Print_String{"Attempting to connect to Server"}
  512.               send$=CP_REQ_CONNECT.s+GAME_NAME.s+Chr$(0)+NET_PROTOCOL_VERSION.s
  513.               WriteUDP{&send$,Len(send$),1}   ; send connection request
  514.             EndIf
  515.           Else
  516.             If online=2
  517.               Print_String{"Already logged on to a Server!"}
  518.             Else
  519.               Print_String{"Already acting as a Server!"}
  520.             EndIf
  521.           EndIf
  522.         Case52           ; Port to connect at above Server
  523.           If Get_Host_By_Name{GTGetString(0,51), GTGetInteger(0,52),1} :EndIf
  524.         Case53           ; put in artificial delay of 1 second for testing purposes
  525.           VWait 50
  526.         Case54           ; get name of localhost
  527.           a$=Localhost_Name {}   ;
  528.           WLocate 315+pingwidth+15,hostnamey+3
  529.           Print a$
  530.         Case63          ; put in artificial delay of 40 seconds for testing purposes- causes you to lose connection
  531.           VWait 3000    ; delay 60s
  532.         Case64         ; Send string message to connected players
  533.          If online>0
  534.              temp$=GTGetString(0,64)
  535.              For i=1 To 8
  536.                If players(i)\status=1  AND i<>my_number   ; send to player if they're online and it's not my number :)
  537.                  Print_String{"S " + Str$(packet_number) + "," + Str$(i)  + ": "+ temp$}
  538.                  send$=REL_STRING_END.s + Mkl$(packet_number) + temp$ + Chr$(0)
  539.                  Send_Reliable_Message{send$,i}   ; Send string to connected players
  540.                EndIf
  541.              Next
  542.          EndIf
  543.        End Select
  544.     EndIf
  545.  
  546.     a$=ReadUDP{}   ; get data from socket
  547.  
  548.     If a$<>""      ; if there was some data waiting
  549.        Decode_Packet{a$}    ; find out what was in the packet
  550.     EndIf
  551.  
  552.     If messages(last_message_number)\ack=False  ; only check if there's messages that haven't been acknowledged yet.
  553.       If Ticks>messages(last_message_number)\timestamp+250  ; has it been 5 secs since the packet was sent?
  554.         If Resend_Message{last_message_number}= False   ; if run out of resends- time out message
  555.           Acknowledge_Packet{message_number}            ; wipe message off message acknowledge array
  556.         EndIf
  557.       EndIf
  558.     EndIf
  559.  
  560.     ev=Event     ; get window events
  561.  
  562. Until ev=$200    ; shut down if close gadget hit
  563.  
  564. CloseUDP{}       ; close UDP socket and buffer down
  565.  
  566. Exit:
  567. WLocate 10,18
  568. Print "                                    "
  569. WLocate 10,18
  570. Print"Socket closed"
  571. Delay_(30)
  572.  
  573. End
  574.  
  575. ;****************************************
  576.  
  577. .Init_Gui            ; setup window and gadgets- note it's a bit hacked from Alvaro Thompson's original code
  578.     WBenchToFront_   ; and isn't proportional and completely font sensitive any more :-/
  579.     WbToScreen0
  580.     DefaultIDCMP $20|$40|$200
  581.     *scr.Screen=Peek.l(Addr Screen(0))
  582.     *myfont.TextAttr=*scr\Font
  583.     fontheight=*myfont\ta_YSize
  584.     ad1.l=*myfont\ta_Name
  585.     fontname$=Peek$(ad1)
  586.  
  587.     LoadFont 1,fontname$,fontheight,0
  588.  
  589.     portwidth=TextLength_(*scr\_RastPort,"Port:",5)+10
  590.     numberswidth=TextLength_(*scr\_RastPort,"99999",5)+14
  591.     serverwidth=TextLength_(*scr\_RastPort,"Send To:",8)+10
  592.     connectwidth=TextLength_(*scr\_RastPort,"Connect",7)+14
  593.     disconnectwidth=TextLength_(*scr\_RastPort,"Disconnect",10)+14
  594.     pingwidth=TextLength_(*scr\_RastPort,"Localhost:",11)
  595.     delaywidth=TextLength_(*scr\_RastPort,"Delay 1s",8)+10
  596.     inputwidth=TextLength_(*scr\_RastPort,"Input:",6)+10
  597.     firstperson=TextLength_(*scr\_RastPort,"1:",2)+10
  598.  
  599.     #SERVERBTN       =51
  600.     #PORTBTN         =52
  601.     #BUTTON          =53
  602.  
  603.     x=1
  604.     y=1
  605.  
  606.     x1=x+(serverwidth*3)+portwidth+numberswidth+9+3+connectwidth+5
  607.  
  608.     If #NO_CONNECTION=0
  609.       GTString  0,#SERVERBTN,x+serverwidth,y,serverwidth*2,fontheight+4,"Send To:",1,256,Localhost_Name {}
  610.     Else
  611.       GTString  0,#SERVERBTN,x+serverwidth,y,serverwidth*2,fontheight+4,"Send To:",1,256,"localhost"
  612.     EndIf
  613.     GTInteger 0,#PORTBTN,x+(serverwidth*3)+portwidth+3,y,numberswidth,fontheight+4,"Port:",1,#PORT
  614.     GTButton  0,#BUTTON,345,y,delaywidth,fontheight+4,"Delay 1s",$10
  615.     GTButton  0,63,340+delaywidth+10,y,delaywidth,fontheight+4,"Delay 1m",$10
  616.     y+fontheight+5
  617.  
  618.     hostnamey=y
  619.  
  620.     GTButton  0,54,315,y,pingwidth,fontheight+4,"Localhost:",$10
  621.  
  622.     WinWidth=x+(serverwidth*3)+portwidth+numberswidth+9+3+connectwidth+8+disconnectwidth+8+90
  623.  
  624.     y+fontheight+5
  625.  
  626.     GTButton  0,55,120,y,firstperson,fontheight+4,"1:",$10
  627.     GTButton  0,56,180,y,firstperson,fontheight+4,"2:",$10
  628.     GTButton  0,57,240,y,firstperson,fontheight+4,"3:",$10
  629.     GTButton  0,58,300,y,firstperson,fontheight+4,"4:",$10
  630.     GTButton  0,59,360,y,firstperson,fontheight+4,"5:",$10
  631.     GTButton  0,60,420,y,firstperson,fontheight+4,"6:",$10
  632.     GTButton  0,61,480,y,firstperson,fontheight+4,"7:",$10
  633.     GTButton  0,62,540,y,firstperson,fontheight+4,"8:",$10
  634.  
  635.     GTString  0,64,50,215,550,fontheight+4,"Send:",1,67,""
  636.  
  637.     WinHeight=y+fontheight+5
  638.  
  639.     ;WinX=WBWidth/2-(WinWidth/2)
  640.     ;WinY=WBHeight/2-(WinHeight/2)
  641.  
  642.     WinTitle$="UDP Chat"
  643.     ;ScreenTitle$="UDP Send "+Chr$(169)+"1997."
  644.  
  645.     Window 0,0,10,WinWidth,245,$0002|$0004|$0008,WinTitle$,1,2
  646.     Use Window 0:Activate 0:AttachGTList 0,0:WTitle WinTitle$,ScreenTitle$:Menus Off
  647.  
  648.     WindowOutput0
  649.     WindowInput 0
  650.  
  651.     a$=Localhost_Name {}   ;
  652.     WLocate 315+pingwidth+15,hostnamey+3
  653.     Print a$
  654.  
  655.     WLocate 10,y+3
  656.     Print"Ping Time-VBL"
  657.  
  658. Return
  659.  
  660.  
  661.